package com.copd.service.impl;

import com.copd.dto.LogCreateRequest;
import com.copd.dto.OperationLogQueryRequest;
import com.copd.entity.DoctorOperationLog;
import com.copd.entity.DoctorOperationDetail;
import com.copd.mapper.DoctorOperationLogMapper;
import com.copd.service.DoctorOperationLogService;
import com.copd.util.TimeUtil;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class DoctorOperationLogServiceImpl implements DoctorOperationLogService {
    
    private static final Logger logger = LoggerFactory.getLogger(DoctorOperationLogServiceImpl.class);
    
    @Autowired
    private DoctorOperationLogMapper logMapper;
    
    @Override
    @Transactional
    public Integer createLog(LogCreateRequest request) {
        // 参数验证
        if (request == null) {
            throw new IllegalArgumentException("请求参数不能为空");
        }
        if (request.getDoctorId() == null) {
            throw new IllegalArgumentException("医生ID不能为空");
        }
        if (request.getPatientId() == null) {
            throw new IllegalArgumentException("患者ID不能为空");
        }
        if (request.getOperationType() == null || request.getOperationType().isEmpty()) {
            throw new IllegalArgumentException("操作类型不能为空");
        }
        
        try {
            // 验证医生ID是否存在, 并确认是医生角色
            if (!logMapper.checkDoctorExists(request.getDoctorId())) {
                throw new IllegalArgumentException("医生ID不存在或者该用户不是医生角色: " + request.getDoctorId());
            }
            
            // 验证患者ID是否存在
            if (request.getPatientId() == null) {
                throw new IllegalArgumentException("患者ID不能为空");
            }
            
            if (!logMapper.checkPatientExists(request.getPatientId())) {
                throw new IllegalArgumentException("患者ID不存在: " + request.getPatientId());
            }
            
            // 创建日志实体
            DoctorOperationLog log = new DoctorOperationLog();
            log.setDoctorId(request.getDoctorId());  // doctorId 对应 Users 表中 role 为 doctor 的 user_id
            log.setPatientId(request.getPatientId());
            log.setOperationType(request.getOperationType());
            log.setIpAddress(request.getIpAddress());
            log.setDeviceInfo(request.getDeviceInfo());
            log.setOperationResult(true); // 默认为成功
            
            // 插入操作日志
            logMapper.insertLog(log);
            Integer logId = log.getLogId();
            
            // 如果有操作详情，插入详情记录
            if (request.getDetailItems() != null && !request.getDetailItems().isEmpty()) {
                for (LogCreateRequest.OperationDetailItem item : request.getDetailItems()) {
                    DoctorOperationDetail detail = new DoctorOperationDetail();
                    detail.setLogId(logId);
                    detail.setDoctorId(request.getDoctorId());
                    detail.setPatientId(request.getPatientId());
                    detail.setTableName(item.getTableName());
                    detail.setRecordId(item.getRecordId());
                    detail.setOperationDetail(item.getOperationDetail());
                    
                    logMapper.insertDetail(detail);
                }
            }
            
            return logId;
        } catch (Exception e) {
            logger.error("创建操作日志失败", e);
            throw new RuntimeException("创建操作日志失败: " + e.getMessage());
        }
    }
    
    @Override
    public Map<String, Object> queryLogs(OperationLogQueryRequest request) {
        // 参数验证和默认值设置
        if (request == null) {
            request = new OperationLogQueryRequest();
        }
        
        logger.info("开始查询操作日志: doctorId={}, patientId={}, page={}, size={}", 
            request.getDoctorId(), request.getPatientId(), request.getPage(), request.getSize());
        
        // 设置默认分页参数
        int page = request.getPage() != null ? request.getPage() : 1;
        int size = request.getSize() != null ? request.getSize() : 10;
        int offset = (page - 1) * size;
        
        try {
            // 查询日志列表 - 使用包装方法，直接传递字符串日期
            List<DoctorOperationLog> logs = logMapper.selectLogsWithStringDates(
                request.getDoctorId(),
                request.getPatientId(),
                request.getDoctorName(),
                request.getPatientName(),
                request.getOperationType(),
                request.getOperationResult(),
                request.getStartTime(),
                request.getEndTime(),
                offset,
                size
            );
            logger.info("查询到{}条操作日志", logs != null ? logs.size() : 0);
            
            // 查询总数 - 使用包装方法，直接传递字符串日期
            long total = logMapper.countLogsWithStringDates(
                request.getDoctorId(),
                request.getPatientId(),
                request.getDoctorName(),
                request.getPatientName(),
                request.getOperationType(),
                request.getOperationResult(),
                request.getStartTime(),
                request.getEndTime()
            );
            logger.info("操作日志总数: {}", total);
            
            // 对每个日志条目，填充详情信息
            for (DoctorOperationLog log : logs) {
                List<DoctorOperationDetail> details = logMapper.selectDetailsByLogId(log.getLogId());
                if (details != null && !details.isEmpty()) {
                    // 设置详情到日志对象中，使其能被序列化返回给前端
                    log.setDetails(details);
                }
            }
            
            // 构建返回结果
            Map<String, Object> result = new HashMap<>();
            result.put("logs", logs);
            result.put("total", total);
            result.put("page", page);
            result.put("size", size);
            
            return result;
        } catch (Exception e) {
            logger.error("查询操作日志失败", e);
            throw new RuntimeException("查询操作日志失败: " + e.getMessage());
        }
    }
    
    @Override
    public Map<String, Object> getLogById(Integer logId) {
        if (logId == null) {
            throw new IllegalArgumentException("日志ID不能为空");
        }
        
        try {
            // 查询日志基本信息
            DoctorOperationLog log = logMapper.selectLogById(logId);
            if (log == null) {
                throw new IllegalArgumentException("未找到ID为" + logId + "的日志");
            }
            
            // 查询操作详情
            List<DoctorOperationDetail> details = logMapper.selectDetailsByLogId(logId);
            
            // 构建返回结果
            Map<String, Object> result = new HashMap<>();
            result.put("log", log);
            result.put("details", details);
            
            return result;
        } catch (Exception e) {
            logger.error("查询日志详情失败", e);
            throw new RuntimeException("查询日志详情失败: " + e.getMessage());
        }
    }
    
    @Override
    @Transactional
    public Integer logPatientOperation(
            Integer doctorId,
            Integer patientId,
            String operationType,
            String ipAddress,
            String deviceInfo,
            boolean isSuccess,
            String failureReason,
            String tableName,
            Integer recordId,
            String detail) {
        
        try {
            // 参数验证
            if (doctorId == null) {
                logger.warn("logPatientOperation: 医生ID为空，跳过日志记录");
                return null;
            }
            
            // 验证医生ID是否存在并且是医生角色
            if (!logMapper.checkDoctorExists(doctorId)) {
                logger.warn("logPatientOperation: 医生ID不存在或用户不是医生角色: " + doctorId + "，跳过日志记录");
                return null;
            }
            
            // 如果patientId为null，设置为0（表示系统操作，非特定患者相关）
            if (patientId == null) {
                logger.info("logPatientOperation: 患者ID为空，不记录操作日志");
                return null;  // 如果没有有效的患者ID，则不记录日志
            }
            
            // 如果有患者ID，验证患者ID是否存在
            if (!logMapper.checkPatientExists(patientId)) {
                logger.warn("logPatientOperation: 患者ID不存在: " + patientId + "，跳过日志记录");
                return null;  // 如果患者ID不存在，则不记录日志
            }
            
            // 创建日志实体
            DoctorOperationLog log = new DoctorOperationLog();
            log.setDoctorId(doctorId);  // doctorId 对应 Users 表中 role 为 doctor 的 user_id
            log.setPatientId(patientId);
            log.setOperationType(operationType);
            log.setIpAddress(ipAddress);
            log.setDeviceInfo(deviceInfo);
            log.setOperationResult(isSuccess);
            log.setFailureReason(failureReason);
            
            // 插入操作日志
            logMapper.insertLog(log);
            Integer logId = log.getLogId();
            
            // 如果有操作详情，插入详情记录
            if (tableName != null && recordId != null && detail != null) {
                DoctorOperationDetail detailEntity = new DoctorOperationDetail();
                detailEntity.setLogId(logId);
                detailEntity.setDoctorId(doctorId);
                detailEntity.setPatientId(patientId);
                detailEntity.setTableName(tableName);
                detailEntity.setRecordId(recordId);
                detailEntity.setOperationDetail(detail);
                
                logMapper.insertDetail(detailEntity);
            }
            
            return logId;
        } catch (Exception e) {
            logger.error("记录患者操作日志失败", e);
            // 这里不抛出异常，避免影响主业务流程
            return null;
        }
    }
    
    @Override
    public boolean checkDoctorExists(Integer doctorId) {
        if (doctorId == null) {
            return false;
        }
        return logMapper.checkDoctorExists(doctorId);
    }
    
    @Override
    public Map<String, Object> queryBackupLogs(OperationLogQueryRequest request) {
        // 参数验证和默认值设置
        if (request == null) {
            request = new OperationLogQueryRequest();
        }
        
        // 如果提供了医生ID，验证医生ID是否存在
        if (request.getDoctorId() != null) {
            if (!logMapper.checkDoctorExists(request.getDoctorId())) {
                throw new IllegalArgumentException("医生ID不存在或者该用户不是医生角色: " + request.getDoctorId());
            }
        }
        
        // 设置默认分页参数
        int page = request.getPage() != null ? request.getPage() : 1;
        int size = request.getSize() != null ? request.getSize() : 10;
        int offset = (page - 1) * size;
        
        try {
            // 定义影响备份表的表名列表
            List<String> backupTables = new ArrayList<>();
            backupTables.add("patient_info");
            backupTables.add("treatment_plans");
            backupTables.add("diagnosis_records");
            backupTables.add("discharge_records");
            backupTables.add("examination_items");
            
            // 如果指定了表名，只查询该表的日志
            String tableName = request.getTableName();
            if (tableName != null && !tableName.isEmpty()) {
                // 如果表名包含_backup，移除后缀获取原表名
                if (tableName.endsWith("_backup")) {
                    tableName = tableName.substring(0, tableName.length() - 7);
                }
                
                // 检查表名是否在备份表列表中
                if (!backupTables.contains(tableName)) {
                    throw new IllegalArgumentException("不支持的备份表: " + tableName);
                }
                
                // 设置为查询参数
                request.setTableName(tableName);
            }
            
            // 使用现有的查询方法，额外过滤表名
            // 由于我们需要通过详情表来过滤表名，先获取所有满足其他条件的日志
            List<DoctorOperationLog> allLogs = logMapper.selectLogsWithStringDates(
                request.getDoctorId(),
                request.getPatientId(),
                request.getDoctorName(),
                request.getPatientName(),
                request.getOperationType(),
                request.getOperationResult(),
                request.getStartTime(),
                request.getEndTime(),
                0, // 先不分页获取所有满足条件的日志
                Integer.MAX_VALUE
            );
            
            // 筛选与备份表相关的日志
            List<DoctorOperationLog> backupRelatedLogs = new ArrayList<>();
            
            for (DoctorOperationLog log : allLogs) {
                // 获取此日志对应的详情记录
                List<DoctorOperationDetail> details = logMapper.selectDetailsByLogId(log.getLogId());
                
                // 检查是否有任何详情涉及备份表
                boolean isRelatedToBackup = false;
                for (DoctorOperationDetail detail : details) {
                    String detailTableName = detail.getTableName();
                    // 如果指定了表名，只匹配指定表
                    if (tableName != null && !tableName.isEmpty()) {
                        if (detailTableName.equals(tableName)) {
                            isRelatedToBackup = true;
                            break;
                        }
                    } else {
                        // 否则匹配任何备份表
                        if (backupTables.contains(detailTableName)) {
                            isRelatedToBackup = true;
                            break;
                        }
                    }
                }
                
                if (isRelatedToBackup) {
                    backupRelatedLogs.add(log);
                }
            }
            
            // 应用分页
            List<DoctorOperationLog> paginatedLogs;
            int fromIndex = offset;
            int toIndex = Math.min(fromIndex + size, backupRelatedLogs.size());
            
            if (fromIndex < backupRelatedLogs.size()) {
                paginatedLogs = backupRelatedLogs.subList(fromIndex, toIndex);
            } else {
                paginatedLogs = new ArrayList<>();
            }
            
            // 构建返回结果
            Map<String, Object> result = new HashMap<>();
            result.put("logs", paginatedLogs);
            result.put("total", backupRelatedLogs.size());
            result.put("page", page);
            result.put("size", size);
            result.put("backupTables", convertToBackupTableInfo(backupTables)); // 添加备份表信息
            
            return result;
        } catch (Exception e) {
            logger.error("查询备份操作日志失败", e);
            throw new RuntimeException("查询备份操作日志失败: " + e.getMessage());
        }
    }
    
    /**
     * 将表名列表转换为带描述的备份表信息
     */
    private List<Map<String, String>> convertToBackupTableInfo(List<String> tables) {
        List<Map<String, String>> result = new ArrayList<>();
        Map<String, String> tableDescMap = new HashMap<>();
        tableDescMap.put("patient_info", "患者基本信息表");
        tableDescMap.put("treatment_plans", "治疗项目记录表");
        tableDescMap.put("diagnosis_records", "患者诊断记录表");
        tableDescMap.put("discharge_records", "出院建议记录表");
        tableDescMap.put("examination_items", "检查项目记录表");
        
        for (String table : tables) {
            Map<String, String> tableInfo = new HashMap<>();
            tableInfo.put("name", table + "_backup");
            tableInfo.put("originalName", table);
            tableInfo.put("description", tableDescMap.getOrDefault(table, ""));
            result.add(tableInfo);
        }
        
        return result;
    }
    
    @Override
    @Transactional
    public boolean deletePatientOperationLogs(Integer patientId) {
        if (patientId == null) {
            throw new IllegalArgumentException("患者ID不能为空");
        }
        
        try {
            // 删除患者相关的所有操作日志
            int result = logMapper.deletePatientOperationLogs(patientId);
            return result >= 0; // 返回true表示操作成功，即使没有记录被删除
        } catch (Exception e) {
            logger.error("删除患者操作日志失败", e);
            throw new RuntimeException("删除患者操作日志失败: " + e.getMessage());
        }
    }
    
    @Override
    public Map<String, Object> queryGroupedLogs(OperationLogQueryRequest request) {
        // 参数验证和默认值设置
        if (request == null) {
            request = new OperationLogQueryRequest();
        }
        
        logger.info("开始查询分组操作日志: doctorId={}, patientId={}, page={}, size={}", 
            request.getDoctorId(), request.getPatientId(), request.getPage(), request.getSize());
        
        // 设置默认分页参数
        int page = request.getPage() != null ? request.getPage() : 1;
        int size = request.getSize() != null ? request.getSize() : 10;
        
        try {
            // 先获取所有满足条件的日志，不分页
            List<DoctorOperationLog> allLogs = logMapper.selectLogsWithStringDates(
                request.getDoctorId(),
                request.getPatientId(),
                request.getDoctorName(),
                request.getPatientName(),
                request.getOperationType(),
                request.getOperationResult(),
                request.getStartTime(),
                request.getEndTime(),
                0,
                Integer.MAX_VALUE
            );
            
            // 按时间和患者ID分组
            Map<String, Map<Integer, List<DoctorOperationLog>>> groupedLogs = new HashMap<>();
            
            for (DoctorOperationLog log : allLogs) {
                // 获取操作时间（转换为精确到分钟的字符串，忽略秒和毫秒）
                String timeKey = TimeUtil.formatDate(log.getOperationTime(), "yyyy-MM-dd HH:mm");
                
                // 获取患者ID
                Integer patientId = log.getPatientId();
                
                // 填充详情信息
                List<DoctorOperationDetail> details = logMapper.selectDetailsByLogId(log.getLogId());
                if (details != null && !details.isEmpty()) {
                    log.setDetails(details);
                }
                
                // 添加到分组中
                if (!groupedLogs.containsKey(timeKey)) {
                    groupedLogs.put(timeKey, new HashMap<>());
                }
                
                if (!groupedLogs.get(timeKey).containsKey(patientId)) {
                    groupedLogs.get(timeKey).put(patientId, new ArrayList<>());
                }
                
                groupedLogs.get(timeKey).get(patientId).add(log);
            }
            
            // 转换成适合前端展示的结构
            List<Map<String, Object>> groupedResults = new ArrayList<>();
            
            for (Map.Entry<String, Map<Integer, List<DoctorOperationLog>>> timeEntry : groupedLogs.entrySet()) {
                String timeKey = timeEntry.getKey();
                Map<Integer, List<DoctorOperationLog>> patientLogs = timeEntry.getValue();
                
                for (Map.Entry<Integer, List<DoctorOperationLog>> patientEntry : patientLogs.entrySet()) {
                    Integer patientId = patientEntry.getKey();
                    List<DoctorOperationLog> logs = patientEntry.getValue();
                    
                    // 创建一个组合项
                    Map<String, Object> groupedItem = new HashMap<>();
                    groupedItem.put("operationTime", timeKey);
                    groupedItem.put("patientId", patientId);
                    
                    // 获取第一个日志的部分信息作为组合项的基本信息
                    if (!logs.isEmpty()) {
                        DoctorOperationLog firstLog = logs.get(0);
                        groupedItem.put("doctorId", firstLog.getDoctorId());
                        groupedItem.put("doctorName", firstLog.getDoctorName());
                        groupedItem.put("patientName", firstLog.getPatientName());
                        groupedItem.put("operationType", firstLog.getOperationType());
                        groupedItem.put("ipAddress", firstLog.getIpAddress());
                        groupedItem.put("deviceInfo", firstLog.getDeviceInfo());
                    }
                    
                    // 收集所有操作详情到一个列表中
                    List<Map<String, Object>> allDetails = new ArrayList<>();
                    for (DoctorOperationLog log : logs) {
                        List<DoctorOperationDetail> details = log.getDetails();
                        if (details != null) {
                            for (DoctorOperationDetail detail : details) {
                                Map<String, Object> detailMap = new HashMap<>();
                                detailMap.put("tableName", detail.getTableName());
                                detailMap.put("recordId", detail.getRecordId());
                                detailMap.put("operationDetail", detail.getOperationDetail());
                                detailMap.put("logId", log.getLogId());
                                allDetails.add(detailMap);
                            }
                        }
                    }
                    
                    groupedItem.put("details", allDetails);
                    groupedResults.add(groupedItem);
                }
            }
            
            // 对结果按时间倒序排序
            groupedResults.sort((a, b) -> {
                String timeA = (String) a.get("operationTime");
                String timeB = (String) b.get("operationTime");
                return timeB.compareTo(timeA); // 降序排列
            });
            
            // 分页处理
            int total = groupedResults.size();
            int startIndex = (page - 1) * size;
            int endIndex = Math.min(startIndex + size, total);
            
            List<Map<String, Object>> pagedResults;
            if (startIndex < total) {
                pagedResults = groupedResults.subList(startIndex, endIndex);
            } else {
                pagedResults = new ArrayList<>();
            }
            
            // 构建返回结果
            Map<String, Object> result = new HashMap<>();
            result.put("logs", pagedResults);
            result.put("total", total);
            result.put("page", page);
            result.put("size", size);
            
            return result;
        } catch (Exception e) {
            logger.error("查询分组操作日志失败", e);
            throw new RuntimeException("查询分组操作日志失败: " + e.getMessage());
        }
    }
} 